package com.example.netty.tcp.server;

import com.example.netty.tcp.message.*;
import com.example.netty.tcp.utils.ExcelReader;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.concurrent.ScheduledFuture;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.example.netty.tcp.message.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.example.netty.tcp.message.ConfigurationQueryRequest;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import io.netty.util.AttributeKey;

public class TestServerHandler extends SimpleChannelInboundHandler<BaseMessage> {
    private static final Logger logger = LoggerFactory.getLogger(TestServerHandler.class);
    private final ObjectMapper mapper = new ObjectMapper(); // 添加 ObjectMapper 实例
    // 模拟电池信息
    private static final Map<String, String> batteryInfo = new HashMap<>();
    private static final AttributeKey<String> DEVICE_ID_KEY = AttributeKey.newInstance("deviceId");
    private boolean isMOSOn = false; // 记录当前MOS状态（false=关闭，true=开启）
    private int controlStep = 0; // 0:关闭全部, 1:开启全部, 2:关闭C, 3:关闭D, 循环
    // 信号量ID（假设01308001支持0-3四种状态）
    private static final String MOS_CONTROL_SIGNAL = "01308001";
    //  声明定时任务句柄（类级变量）
    private ScheduledFuture<?> controlScheduler;
    // 使用双反斜杠路径
    private static final Map<String, String> signalMap = ExcelReader.readExcel(
            "D:\\nettyTestTcpConcernedFile\\能源业务换电设备信号量字典表V3.0(1).xlsx"
    );
    static {
        batteryInfo.put("01113001", "80"); // SOC
        batteryInfo.put("01111001", "3600"); // 总电压（放大100倍）
        batteryInfo.put("01115001", "1000"); // 剩余容量（放大100倍）
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        logger.info("客户端连接建立: {}", ctx.channel().remoteAddress());

        //先把你关了，测试充放电mos
//        // 连接建立后，定时发送配置查询
//        ctx.executor().scheduleAtFixedRate(() -> {
//            if (ctx.channel().isActive()) {
//                // 从LoginRequest中获取deviceId（需在channelRead0中保存）
//                String deviceId = getDeviceIdFromChannel(ctx);
//                if (deviceId != null) {
//                    sendConfigurationQuery(ctx, deviceId);
//                }
//            }
//        }, 20, 60, TimeUnit.SECONDS); // 20秒后开始，每60秒发送一次

// ✅ 新增：定时控制MOS任务（20秒后首次执行，30秒间隔）
        ChannelHandlerContext finalCtx = ctx;
        controlScheduler = ctx.executor().scheduleAtFixedRate(() -> executeControlStep(finalCtx), 20, 30, TimeUnit.SECONDS);

    }
    private void executeControlStep(ChannelHandlerContext ctx) {
        String deviceId = getDeviceIdFromChannel(ctx);
        if (deviceId == null) {
            return;
        }

        String command = "0"; // 默认关闭全部
        switch (controlStep) {
            case 0:
                command = "0"; // 关闭C/D FET
                logger.info("执行步骤1：关闭全部MOS");
                break;
            case 1:
                command = "3"; // 开启C/D FET
                logger.info("执行步骤2：开启全部MOS");
                break;
            case 2:
                command = "1"; // 关闭C FET（单独关闭充电MOS）
                logger.info("执行步骤3：单独关闭C FET");
                break;
            case 3:
                command = "2"; // 关闭D FET（单独关闭放电MOS）
                logger.info("执行步骤4：单独关闭D FET");
                controlStep = -1; // 重置步骤，循环执行
                break;
            default:
                return;
        }

        sendMOSControl(ctx, deviceId, command);
        controlStep++;
    }
    // TestServerHandler.java
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, BaseMessage msg) {
        try {
            logger.debug("1. 进入 channelRead0 方法");
            String json = mapper.writeValueAsString(msg);
            logger.debug("2. 消息转换为 JSON 字符串: {}", json);

            if (msg instanceof LoginRequest) {
                logger.debug("3. 检测到 LoginRequest 类型消息");
                handleLoginRequest(ctx, (LoginRequest) msg);
            } else if (msg instanceof AlarmReport) {
                logger.debug("3. 检测到 AlarmReport  类型消息");
                handleAlarmReport(ctx, (AlarmReport) msg);
            } else if (msg instanceof AttributeReport) {
                logger.debug("3. 检测到 AttributeReport  类型消息");
                handleAttributeReport(ctx, (AttributeReport) msg);
            } else if (msg instanceof ControlRequest) {
                logger.debug("4. 检测到 ControlRequest 类型消息");
                handleControlRequest(ctx, (ControlRequest) msg);
            } else if (msg instanceof ControlResponse) { // 新增：处理控制响应（501）
                handleControlResponse(ctx, (ControlResponse) msg);
            } else if (msg instanceof HeartbeatRequest) {
                logger.debug("4. 检测到 HeartbeatRequest 类型消息");
                handleHeartbeat(ctx);
            } else {
                logger.info("3. 收到未知类型消息: {}", msg.getClass().getName());
            }
        } catch (Exception e) {
            logger.error("4. 捕获异常", e);
        }
    }
    // 新增：处理告警上报请求的方法
    private void handleAlarmReport(ChannelHandlerContext ctx, AlarmReport report) {
        logger.info("服务器收到告警上报: 设备ID={}, 告警数量={}",
                report.getDevId(), report.getAlarmList().size());

        // 打印告警详情
        for (AlarmReport.Alarm alarm : report.getAlarmList()) {
            String signalName = signalMap.get(alarm.getId());
            logger.info("  信号标准名: {}, 告警描述: {}, 时间: {}",
                    signalName != null ? signalName : alarm.getId(),
                    alarm.getAlarmDesc(),
                    alarm.getAlarmTime());
        }

        // 返回告警上报响应（服务器需响应客户端）
        AlarmReportResponse response = new AlarmReportResponse();
        response.setDevId(report.getDevId());
        response.setResult(1); // 成功
        response.setTxnNo(report.getTxnNo());
        ctx.writeAndFlush(response);
        logger.info("服务器已响应告警上报");
    }
    // 新增：主动发送MOS控制指令的方法
    private void sendMOSControl(ChannelHandlerContext ctx, String deviceId, String command) {
        ControlRequest request = new ControlRequest();
        request.setDevId(deviceId);
        request.setTxnNo(System.currentTimeMillis());
        request.addControlParam(MOS_CONTROL_SIGNAL, command); // 信号量ID=01308001（文档5-157）

        ctx.writeAndFlush(request);
        logger.info("发送远程控制请求（500）：开启MOS，指令={}", command);
    }
    private void handleConfigurationQueryResponse(ChannelHandlerContext ctx, ConfigurationQueryResponse response) {
        logger.info("收到配置查询响应，设备ID: {}", response.getDevId());

        if (response.getResult() == 1) {
            for (ConfigurationQueryResponse.Result result : response.getResultList()) {
                logger.info("信号量ID: {}, 值: {}", result.getId(), result.getValue());

                // 这里可以根据信号量ID处理具体业务逻辑
                processSignalValue(result.getId(), result.getValue());
            }
        } else {
            logger.warn("配置查询失败，设备ID: {}", response.getDevId());
        }
    }

    // 定时发送配置查询请求
    private void sendConfigurationQuery(ChannelHandlerContext ctx, String deviceId) {
        ConfigurationQueryRequest request = new ConfigurationQueryRequest();
        request.setDevId(deviceId);
        request.setTxnNo(System.currentTimeMillis());

        // 添加需要查询的信号量ID
        request.addParameter("01113001"); // SOC
        request.addParameter("01111001"); // 总电压
        request.addParameter("01115001"); // 剩余容量

        ctx.writeAndFlush(request);
        logger.info("向设备[{}]发送配置查询请求", deviceId);
    }

//    @Override
//    public void channelActive(ChannelHandlerContext ctx) {
//
//    }


    // 从Channel中获取deviceId（需在登录时保存）
    private String getDeviceIdFromChannel(ChannelHandlerContext ctx) {
        // 从Channel属性中获取设备ID（登录时存储）
        return ctx.channel().attr(DEVICE_ID_KEY).get();
    }


    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;

        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        logger.error("服务器发生异常: {}", cause.getMessage());
        ctx.close();
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        logger.info("客户端连接断开: {}", ctx.channel().remoteAddress());
    }

    private void handleLoginRequest(ChannelHandlerContext ctx, LoginRequest request) {
        logger.info("收到登录请求: 设备ID={}, IMSI={}",
                request.getDevId(), request.getImsi());
        // 新增：存储设备ID到Channel属性
        ctx.channel().attr(DEVICE_ID_KEY).set(request.getDevId());
        // 新增协议版本校验
        if (!"V5.0".equals(request.getProtocolVersion())) {
            logger.error("不支持的协议版本: {}", request.getProtocolVersion());
            ctx.close();
            return;
        }
        // 返回登录成功响应
        LoginResponse response = new LoginResponse();
        response.setDevId(request.getDevId());
        response.setResult(1); // 1:成功
        response.setTxnNo(request.getTxnNo()); // 与请求流水号一致
        ctx.writeAndFlush(response);
        logger.info("发送登录响应（111）成功");

        //  主动发送控制请求（500）：登录成功后延迟2秒发送（使用局部变量）
        ScheduledFuture<?> future = ctx.executor().schedule(() -> {
            sendMOSControl(ctx, request.getDevId(), "3"); // 3=开启充电MOS（文档5-157）
        }, 2, TimeUnit.SECONDS);
    }

    private void handleAttributeReport(ChannelHandlerContext ctx, AttributeReport report) {
        logger.info("收到属性上报: 设备ID={}, 属性数量={}",
                report.getDevId(), report.getAttrList().size());

        // 打印所有属性
        for (AttributeReport.Attribute attr : report.getAttrList()) {
            String signalName = signalMap.get(attr.getId());
            if (signalName != null) {
                logger.info("  信号标准名: {}, 值: {}", signalName, attr.getValue());
            } else {
                logger.info("  信号量ID: {}, 值: {}", attr.getId(), attr.getValue());
            }
        }

        // 返回属性上报响应
        AttributeReportResponse response = new AttributeReportResponse();
        response.setDevId(report.getDevId());
        response.setResult(1); // 成功
        response.setTxnNo(report.getTxnNo());
        ctx.writeAndFlush(response);
    }

    private void handleHeartbeat(ChannelHandlerContext ctx) {
        logger.info("收到心跳包");
        HeartbeatResponse response = new HeartbeatResponse();
        ctx.writeAndFlush(response);
    }

    private void handleConfigurationQueryRequest(ChannelHandlerContext ctx, ConfigurationQueryRequest request) {
        logger.info("收到配置查询请求: 设备ID={}", request.getDevId());

        ConfigurationQueryResponse response = new ConfigurationQueryResponse();
        response.setDevId(request.getDevId());
        response.setResult(1);
        response.setTxnNo(request.getTxnNo());

        for (ConfigurationQueryRequest.Parameter param : request.getParamList()) {
            String id = param.getId();
            String value = batteryInfo.get(id);
            if (value != null) {
                response.addResult(id, value);
            }
        }

        ctx.writeAndFlush(response);
    }

    // 处理信号量值的业务逻辑
    private void processSignalValue(String signalId, String value) {
        // 根据不同信号量ID执行不同操作
        switch (signalId) {
            case "01113001":
                // 处理SOC值
                double soc = Double.parseDouble(value) / 100.0;
                logger.info("电池SOC: {}%", soc);
                break;
            case "01111001":
                // 处理总电压
                double voltage = Double.parseDouble(value) / 100.0;
                logger.info("电池总电压: {}V", voltage);
                break;
            // 其他信号量处理...
        }
    }
    // 处理控制请求（原有逻辑优化）
    private void handleControlRequest(ChannelHandlerContext ctx, ControlRequest request) {
        logger.info("收到远程控制请求: 设备ID={}, 信号量ID={}, 值={}",
                request.getDevId(),
                request.getParamList().get(0).getId(),
                request.getParamList().get(0).getValue());

        // 验证信号量ID是否为MOS控制（01308001）
        if ("01308001".equals(request.getParamList().get(0).getId())) {
            String command = request.getParamList().get(0).getValue();
            handleMOSControl(ctx, request.getDevId(), command);
        } else {
            logger.warn("不支持的信号量ID: {}", request.getParamList().get(0).getId());
            sendControlResponse(ctx, request, 0, "无效信号量ID");
            return;
        }
    }

    // 优化：统一响应处理
    private void sendControlResponse(ChannelHandlerContext ctx, ControlRequest request, int result, String errorMsg) {
        ControlResponse response = new ControlResponse();
        response.setDevId(request.getDevId());
        response.setTxnNo(request.getTxnNo());
        response.setResult(result);
        response.setErrorMessage(errorMsg);
        ctx.writeAndFlush(response);
        logger.info("返回控制响应：result={}, 设备ID={}", result, request.getDevId());
    }

    private void handleMOSControl(ChannelHandlerContext ctx, String deviceId, String command) {
        logger.info("执行MOS控制指令: 设备ID={}, 指令={}", deviceId, command);

        if (!"0".equals(command) && !"3".equals(command)) {
            sendControlResponse(ctx, null, 0, "无效指令，仅支持0或3");
            return;
        }
        // 这里添加实际控制逻辑（如与硬件交互）
        // 示例：根据command值控制MOS开关状态（0:关闭C/D FET，3:开启C/D FET等）
        switch (command) {
            case "0":
                logger.info("成功关闭充电/放电MOS（C/D FET关闭）");
                // 执行关闭操作
                break;
            case "3":
                logger.info("成功开启充电/放电MOS（C/D FET开启）");
                // 执行开启操作
                break;
            default:

        }
        // 控制成功后，可触发相关遥测上报（根据文档要求）
        triggerMOSStatusReport(ctx, deviceId, command);
    }

    private void handleControlResponse(ChannelHandlerContext ctx, ControlResponse response) {
        logger.info("收到控制响应（501）：设备ID={}, 结果={}",
                response.getDevId(),
                response.getResult() == 1 ? "成功" : "失败");

        if (response.getResult() == 1) {
            logger.info("MOS控制成功，流水号={}", response.getTxnNo());
            // 可在此添加后续逻辑，如上报状态
        } else {
            logger.error("MOS控制失败，原因：{}", response.getErrorMessage());
        }
    }
    // 新增：控制成功后上报MOS状态（可选，根据文档1.6.2要求）
    private void triggerMOSStatusReport(ChannelHandlerContext ctx, String deviceId, String command) {
        AttributeReport report = new AttributeReport();
        report.setDevId(deviceId);
        report.setTxnNo(System.currentTimeMillis());

        // 上报C_FET和D_FET状态（假设指令3为开启，状态为1）
        String status = "1"; // 1表示开启，0表示关闭
        report.addAttribute("01311001", status); // C_FET状态
        report.addAttribute("01312001", status); // D_FET状态

        ctx.writeAndFlush(report);
        logger.info("上报MOS状态：C_FET和D_FET状态为{}", status);
    }
}

